import { dom, Nodes } from '@knno/dom';
import { button } from '../button/button';
import { input, InputType } from '../input/input';
import { alertBox, dialogStyle, dangerIcon, dialogPanel } from './dialog.css';
import '../../dict';
import SVGWarning from '@material-design-icons/svg/filled/warning.svg';
import SVGError from '@material-design-icons/svg/filled/error_outline.svg';
import SVGSuccess from '@material-design-icons/svg/filled/done.svg';
import SVGTips from '@material-design-icons/svg/filled/tips_and_updates.svg';
import SVGQuestion from '@material-design-icons/svg/filled/question_mark.svg';
import { vars } from '../global.css';
import { DialogBase } from './dialogBase';
import { DICT } from '../../dict';

type Button = ReturnType<typeof button>;

class DialogBox extends DialogBase {
	protected get box(): Nodes {
		return this.query(`div.${dialogPanel}>div.content`);
	}
	protected getPanel(): Nodes {
		return this.query(`div.${dialogPanel}`);
	}
	constructor() {
		const panel = dom.div(dialogPanel).attr('tabindex', '0').append(dom.h2(), dom.div('content'), dom.div('bar'));
		super(dom.div(dialogStyle, 'dialog').append(dom.div('container').append(panel)));
	}

	buttons(...buttons: Button[]): this {
		this.query(`div.${dialogPanel}>div.bar`)
			.html('')
			.append(...buttons);
		return this;
	}

	title(title: string): this {
		this.query(`div.${dialogPanel}>h2`).text(title);
		return this;
	}
}

function iconAlert(
	icon: string | null,
	color: string,
	cancelButton = false
): (msg: string, title?: string) => Promise<boolean> {
	return (msg: string, title?: string) => {
		return new Promise<boolean>((resolve) => {
			let result = false;
			const dlg = Dialog.create(
				dom.div(alertBox).append(icon ? dom.html(icon).attr('class', dangerIcon).css('fill', color) : [], dom.text(msg))
			).on('close', () => {
				resolve(result);
			});
			const btns = [
				button()
					.text(DICT.ok)
					.type('primary')
					.on('click', () => {
						result = true;
						dlg.close('ok');
					}),
			];
			if (cancelButton) {
				dlg.escClose(true);
				btns.splice(
					0,
					0,
					button()
						.text(DICT.cancel)
						.on('click', () => {
							dlg.close();
						})
				);
			}
			dlg.buttons(...btns);
			if (title) {
				dlg.title(title);
			}
			dlg.on('keypress', (evt) => {
				if (evt.key === 'Enter') {
					btns[cancelButton ? 1 : 0].emit(new MouseEvent('click'));
				}
			});
			dlg.show();
		});
	};
}

interface PromptOption {
	message?: string;
	title?: string;
	placeholder?: string;
	type?: InputType;
	maxLength?: number;
	verify?: RegExp;
	verifyMessage?: string;
}

export const Dialog = {
	create(...elem: (Text | Element | (Element | Text)[])[]): DialogBox {
		return new DialogBox().append(...elem);
	},
	alert: iconAlert(null, ''),
	error: iconAlert(SVGError, vars.color.danger),
	success: iconAlert(SVGSuccess, vars.color.success),
	warning: iconAlert(SVGWarning, vars.color.warning),
	tips: iconAlert(SVGTips, vars.color.warning),
	confirm: iconAlert(SVGQuestion, vars.color.brand, true),
	prompt(options: PromptOption = {}): Promise<string | null> {
		return new Promise<string | null>((resolve) => {
			let result: string | null = null;
			const ipt = input();
			if (options.type) {
				ipt.type(options.type);
			}
			if (options.maxLength) {
				ipt.maxLength(options.maxLength);
			}
			if (options.placeholder !== undefined) {
				ipt.placeholder(options.placeholder);
			}
			ipt.on('input', () => {
				errDiv.text('');
			});
			ipt.on('keydown', (e) => {
				if (e.key === 'Enter') {
					onOK();
				}
			});
			const errDiv = dom.div().css({
				color: vars.color.danger,
				textAlign: 'left',
				margin: '0.5em 0',
			});
			const dlg = this.create(
				options.message ? dom.p().css('textAlign', 'left').text(options.message) : [],
				ipt,
				errDiv
			)
				.escClose(true)
				.on('close', () => {
					resolve(result);
				})
				.buttons(
					button()
						.text(DICT.cancel)
						.on('click', () => {
							dlg.close();
						}),
					button()
						.text(DICT.ok)
						.type('primary')
						.on('click', () => {
							onOK();
						})
				)
				.show({ focusElement: ipt });
			// .on('open', () => {
			// 	ipt.focus();
			// });
			if (options.title) {
				dlg.title(options.title);
			}
			function onOK() {
				result = ipt.text();
				if ((options.verify ?? /[^\s]+/).test(result)) {
					dlg.close('ok');
				} else {
					errDiv.text(options.verifyMessage ?? DICT.inputError);
					result = null;
					ipt.focus();
				}
			}
		});
	},
};
